#include "window.h"
#include <QOpenGLContext>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QtCore/QCoreApplication>
#include <QDebug>

static const char *vertexShaderSource =
    "attribute vec4 position;\n"
    "void main() {\n"
    "   gl_Position = position;\n"
    "}\n";

static const char *fragmentShaderSource =
    "void main() {\n"
        "gl_FragColor = vec4(0.0f, 1.0f, 0.3f, 1.0f);\n"
    "}\n";

const float vertexPositions[] = {
    0.5f, 0.5f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.0f, 1.0f,
    -0.5f, -0.5f, 0.0f, 1.0f,
};

Window::Window() :
    QWindow()
{
    setSurfaceType(OpenGLSurface);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setMajorVersion(4);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile(QSurfaceFormat::CoreProfile);
    setFormat(format);
    create();

    m_context = new QOpenGLContext;
    m_context->setFormat(format);
    m_context->create();

    m_context->makeCurrent(this);

    if(!m_context->versionFunctions())
    {
        qWarning("Could not obtain OpenGL versions object");
        exit(1);
    }
    initializeOpenGLFunctions();
    const char* str = (const char *)glGetString(GL_VERSION);
    qWarning() << str;

    initialize();
}

Window::~Window()
{
    delete m_context;
    m_program->release();
    delete m_program;
    delete m_buffer;
}

void Window::initialize()
{
    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();

    m_buffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    m_buffer->create();
    m_buffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
    m_buffer->bind();

//    int location = m_program->attributeLocation("position");
//    m_program->enableAttributeArray(location);
//    m_program->setAttributeArray(location, GL_FLOAT, NULL, 4);
    m_program->enableAttributeArray("position");
    m_program->setAttributeBuffer("position", GL_FLOAT, NULL, 4);

    m_buffer->allocate(vertexPositions, sizeof(vertexPositions));
    m_buffer->release();
    m_program->release();
}

void Window::render()
{
    glViewport(0, 0, width(), height());
    m_context->makeCurrent(this);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    m_program->bind();
    m_buffer->bind();
    glDrawArrays(GL_TRIANGLES, 0, 3);
    m_context->swapBuffers(this);
}

void Window::exposeEvent(QExposeEvent *event)
{
    Q_UNUSED(event);
    if(isExposed())
        render();
}
